﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly: WebResource("ExtJSExtender.Controls.Grid.GridPanelExtenderBehavior.js", "text/javascript")]

namespace ExtJSExtender.Controls
{
    [ToolboxData("<{0}:GridPanel runat=\"server\"></{0}:GridPanel>")]
    [ToolboxBitmap(typeof(GridView))]
    public class GridPanel : ExtJSControlBase, IPostBackEventHandler, INamingContainer, IPostBackDataHandler, ICallbackEventHandler
    {
        #region 属性

        /// <summary>
        /// 主键字段，选择时将保存该字段的值
        /// </summary>
        [ExtJSExtender.DescribableProperty("KeyField")]
        public string KeyField
        {
            get
            {
                if (ViewState["KeyField"] == null)
                    ViewState["KeyField"] = string.Empty;
                return (string)ViewState["KeyField"];
            }
            set
            {
                ViewState["KeyField"] = value;
            }
        }

        /// <summary>
        /// Header要显示的文本
        /// </summary>
        [ExtJSExtender.DescribableProperty("Title")]
        public string Title
        {
            get
            {
                if (ViewState["Title"] == null)
                    ViewState["Title"] = string.Empty;
                return (string)ViewState["Title"];
            }
            set
            {
                ViewState["Title"] = value;
            }
        }

        /// <summary>
        /// 边框的宽度
        /// </summary>
        public Unit Border
        {
            get
            {
                if (ViewState["Border"] == null)
                    ViewState["Border"] = new Unit(1);

                return (Unit)ViewState["Border"];
            }
            set
            {
                ViewState["Border"] = value;
            }
        }

        /// <summary>
        /// 是否自动回发
        /// </summary>
        [ExtJSExtender.DescribableProperty("AutoPostBack")]
        public bool AutoPostBack
        {
            get
            {
                if (ViewState["AutoPostBack"] == null)
                    ViewState["AutoPostBack"] = false;
                return (bool)ViewState["AutoPostBack"];
            }
            set
            {
                ViewState["AutoPostBack"] = value;
            }
        }

        //private int _default_PageSize = 25;
        /// <summary>
        /// 每页显示多少行数据
        /// </summary>
        [ExtJSExtender.DescribableProperty("PageSize")]
        public int PageSize
        {
            get
            {
                return this.DataStore.PageSize;
            }
            set
            {
                this.DataStore.PageSize = value;
            }
            //get
            //{
            //    if (ViewState["PageSize"] == null)
            //        return _default_PageSize;
            //    return (int)ViewState["PageSize"];
            //}
            //set
            //{
            //    ViewState["PageSize"] = value;
            //}
        }

        /// <summary>
        /// 是否分页显示
        /// </summary>
        [ExtJSExtender.DescribableProperty("Pagination")]
        public bool Pagination
        {
            get
            {
                if (ViewState["Pagination"] == null)
                    ViewState["Pagination"] = false;
                return (bool)ViewState["Pagination"];
            }
            set
            {
                ViewState["Pagination"] = value;
            }
        }

        /// <summary>
        /// 是否可编辑
        /// </summary>
        [ExtJSExtender.DescribableProperty("EnableEdit")]
        public bool EnableEdit
        {
            get
            {
                if (ViewState["EnableEdit"] == null)
                    ViewState["EnableEdit"] = false;
                return (bool)ViewState["EnableEdit"];
            }
            set
            {
                ViewState["EnableEdit"] = value;
            }
        }

        /// <summary>
        /// 触发编辑的事件
        /// </summary>
        public GridEditTriggerEvent EditTriggerEvent
        {
            get
            {
                if (ViewState["EditTriggerEvent"] == null)
                    ViewState["EditTriggerEvent"] = GridEditTriggerEvent.cellclick;
                return (GridEditTriggerEvent)ViewState["EditTriggerEvent"];
            }
            set
            {
                ViewState["EditTriggerEvent"] = value;
            }
        }

        /// <summary>
        /// 显示行号列
        /// </summary>
        [ExtJSExtender.DescribableProperty("ShowRowNumberColumn")]
        public bool ShowRowNumberColumn
        {
            get
            {
                if (ViewState["ShowRowNumberColumn"] == null)
                    ViewState["ShowRowNumberColumn"] = false;
                return (bool)ViewState["ShowRowNumberColumn"];
            }
            set
            {
                ViewState["ShowRowNumberColumn"] = value;
            }
        }

        /// <summary>
        /// 显示选择列
        /// </summary>
        [ExtJSExtender.DescribableProperty("ShowSelectionColumn")]
        public bool ShowSelectionColumn
        {
            get
            {
                if (ViewState["ShowSelectionColumn"] == null)
                    ViewState["ShowSelectionColumn"] = false;
                return (bool)ViewState["ShowSelectionColumn"];
            }
            set
            {
                ViewState["ShowSelectionColumn"] = value;
            }
        }

        /// <summary>
        /// 获取数据的地址，在请求的时候，如果节点的id属性存在，则会作为请求参数传递
        /// </summary>
        [ExtJSExtender.DescribableProperty("DataUrl")]
        public string DataUrl
        {
            get
            {
                return this.DataStore.DataUrl;
            }
            set
            {
                this.DataStore.DataUrl = value;
            }
            //get
            //{
            //    if (ViewState["DataUrl"] == null)
            //        return string.Empty;
            //    return (string)ViewState["DataUrl"];
            //}
            //set
            //{
            //    ViewState["DataUrl"] = value;
            //}
        }

        /// <summary>
        /// 选择方式
        /// </summary>
        public GridSelectionMode SelectionMode
        {
            get
            {
                if (ViewState["SelectionMode"] == null)
                    ViewState["SelectionMode"] = GridSelectionMode.Single;
                return (GridSelectionMode)ViewState["SelectionMode"];
            }
            set
            {
                ViewState["SelectionMode"] = value;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty), Bindable(true), Localizable(true)]
        public GridColumnCollection Columns
        {
            get
            {
                if (ViewState["Columns"] == null)
                    ViewState["Columns"] = new GridColumnCollection();
                return (GridColumnCollection)ViewState["Columns"];
            }
            set
            {
                ViewState["Columns"] = value;
            }
        }

        /// <summary>
        /// 所有选中的记录，数据存储在BehaviorState中
        /// </summary>
        [Bindable(false)]
        public List<string> AllSelectedValues
        {
            get
            {
                return this.BehaviorState.AllSelectedValues;
            }
            set
            {
                this.BehaviorState.AllSelectedValues = value;
            }
        }

        private GridBehaviorState behaviorState = null;
        [Bindable(false)]
        public GridBehaviorState BehaviorState
        {
            get
            {
                if (behaviorState == null)
                    behaviorState = new GridBehaviorState();

                return behaviorState;
            }
            set
            {
                behaviorState = value;
            }
            //get
            //{
            //    if (ViewState["BehaviorState"] == null)
            //        ViewState["BehaviorState"] = new GridBehaviorState();
            //    return (GridBehaviorState)ViewState["BehaviorState"];
            //}
            //set
            //{
            //    ViewState["BehaviorState"] = value;
            //}
        }

        private GridDataStore dataStore = null;
        public GridDataStore DataStore
        {
            get
            {
                if (dataStore == null)
                    dataStore = new GridDataStore();
                return dataStore;
            }
            set
            {
                dataStore = value;
            }
        }

        [ExtJSExtender.DescribableProperty("TriggerPostBackEvents")]
        [PersistenceMode(PersistenceMode.InnerProperty), Bindable(true), Localizable(true)]
        public GridTriggerPostBackEvents TriggerPostBackEvents
        {
            get
            {
                if (ViewState["TriggerPostBackEvents"] == null)
                    ViewState["TriggerPostBackEvents"] = new GridTriggerPostBackEvents();

                return (GridTriggerPostBackEvents)ViewState["TriggerPostBackEvents"];
            }
            set
            {
                ViewState["TriggerPostBackEvents"] = value;
            }
        }

        #endregion

        #region 构造函数

        public GridPanel()
            : base(HtmlTextWriterTag.Div)
        {

        }

        #endregion

        #region 事件

        public event RowSelectChangedEventHandler RowSelectChanged;
        public event RowCommandEventHandler RowCommand;
        public event LoadPageDataEventHandler LoadPageData;

        #endregion

        #region 数据绑定

        #endregion

        #region 公用方法


        #endregion

        #region 只读属性，处理控件的值及事件等

        [ExtJSExtender.DescribableProperty("DataFields")]
        public List<string> DataFields
        {
            get
            {
                var columns = this.Columns;

                List<string> fields = new List<string>();
                
                //定义的Columns
                for (int i = 0; i < columns.Count; i++)
                {
                    if (!string.IsNullOrWhiteSpace(columns[i].DataField))
                        fields.Add(columns[i].DataField);
                }

                //主键列
                if (string.IsNullOrWhiteSpace(this.KeyField) && !fields.Contains(this.KeyField))
                    fields.Add(this.KeyField);

                return fields;
            }
        }

        [ExtJSExtender.DescribableProperty("DataStoreHiddenField")]
        public string DataStore_HiddenField_ClientID
        {
            get { return this.ClientID + "_DataStore"; }
        }

        [ExtJSExtender.DescribableProperty("BehaviorStateHiddenField")]
        public string BehaviorState_HiddenField_ClientID
        {
            get { return this.ClientID + "_BehaviorState"; }
        }

        #endregion

        #region WebControl 方法重写

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            //加载回发的数据
            this.LoadPostData(this.ClientID, this.Page.Request.Params);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!this.Page.IsPostBack)
            {
                //触发加载数据的事件
                if (this.TriggerPostBackEvents.LoadPageData && LoadPageData != null)
                {
                    LoadPageDataEventArgs args = new LoadPageDataEventArgs();
                    args.DataStore = this.DataStore;
                    args.DataStore.CurrentPage = 1;
                    args.CurrentPage = args.DataStore.CurrentPage;
                    args.PageSize = args.DataStore.PageSize;

                    LoadPageData.Invoke(this, args);
                }
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);

            //将DataStore数据写在客户端隐藏域中
            Util.RenderHiddenField(writer, this.DataStore_HiddenField_ClientID, Util.SerializeToJson(this.DataStore));

            //将BehaviorState写在客户端隐藏域中
            Util.RenderHiddenField(writer, this.BehaviorState_HiddenField_ClientID, Util.SerializeToJson(this.BehaviorState));
        }

        #endregion

        #region ExtScriptWebControlBase 成员

        public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor("ExtJSExtender.Controls.GridPanelExtenderBehavior", this.ClientID);

            descriptor.AddProperty("Enabled", Enabled);
            descriptor.AddProperty("Width", this.Width.Value);
            descriptor.AddProperty("Height", this.Height.Value);
            descriptor.AddProperty("Border", this.Border.Value);
            descriptor.AddProperty("UniqueID", this.UniqueID);
            descriptor.AddProperty("Columns", Util.SerializeToJson(this.Columns));
            descriptor.AddProperty("SelectionMode", this.SelectionMode.ToString());
            descriptor.AddProperty("EditTriggerEvent", this.EditTriggerEvent.ToString());

            ExtJSExtender.Util.DescribeProperties(this, descriptor);

            var descriptors = base.GetScriptDescriptors().ToList();
            descriptors.Add(descriptor);
            return descriptors;
        }

        public override IEnumerable<ScriptReference> GetScriptReferences()
        {
            var reference = new ScriptReference();
            reference.Assembly = "ExtJSExtender.Controls";
            reference.Name = "ExtJSExtender.Controls.Grid.GridPanelExtenderBehavior.js";

            var references = base.GetScriptReferences().ToList();
            references.Add(reference);
            return references;
        }

        #endregion

        #region IPostBackDataHandler 成员

        public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
        {
            if (Page.IsPostBack)
            {
                //得到客户端的数据行
                string dataStoreString = Context.Request[this.DataStore_HiddenField_ClientID];
                if (!string.IsNullOrEmpty(dataStoreString))
                {
                    this.DataStore = Util.DeserializeJson<GridDataStore>(dataStoreString);
                    //this.DataStore.DataUrl = this.DataUrl;
                    //this.DataStore.PageSize = this.PageSize;
                }

                // 得到客户端选中的状态
                string behaviorStateString = Context.Request[this.BehaviorState_HiddenField_ClientID];
                if (!string.IsNullOrEmpty(behaviorStateString))
                {
                    this.BehaviorState = Util.DeserializeJson<GridBehaviorState>(behaviorStateString);
                    this.BehaviorState.NeedResetScroll = 0;
                }
            }

            return false;
        }

        public void RaisePostDataChangedEvent()
        {
            //如果LoadPostData返回true，此方法将被调用，此处不处理
        }

        #endregion

        #region IPostBackEventHandler 成员

        public void RaisePostBackEvent(string eventArgument)
        {
            RaiseCallbackEvent(eventArgument);
        }

        #endregion

        #region ICallbackEventHandler 成员

        public string GetCallbackResult()
        {
            return null;
        }

        public void RaiseCallbackEvent(string eventArgument)
        {
            ExtJSEventArgs extJSEventArgs = Util.DeserializeJson<ExtJSEventArgs>(eventArgument);
            if (extJSEventArgs == null)
                return;

            switch (extJSEventArgs.EventName)
            {
                case "RowSelectChanged":
                    {
                        if (RowSelectChanged != null)
                        {
                            RowSelectChangedEventArgs eventArgs = Util.DeserializeJson<RowSelectChangedEventArgs>(extJSEventArgs.Arguments);
                            eventArgs.AllSelectedValues = this.AllSelectedValues;
                            RowSelectChanged.Invoke(this, eventArgs);
                        }
                    }
                    break;
                case "RowCommand":
                    {
                        if (RowCommand != null)
                        {
                            RowCommandEventArgs eventArgs = Util.DeserializeJson<RowCommandEventArgs>(extJSEventArgs.Arguments);
                            RowCommand.Invoke(this, eventArgs);
                        }
                    }
                    break;
                case "LoadPageData":
                    {
                        if (LoadPageData != null)
                        {
                            LoadPageDataEventArgs eventArgs = Util.DeserializeJson<LoadPageDataEventArgs>(extJSEventArgs.Arguments);
                            eventArgs.DataStore = this.DataStore;
                            this.DataStore.CurrentPage = eventArgs.CurrentPage;
                            this.DataStore.PageSize = eventArgs.PageSize;

                            LoadPageData.Invoke(this, eventArgs);
                        }
                    }
                    break;
            }
        }

        #endregion
    }
}
